/**
 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Autogenerated file. DO NOT EDIT
package std.core;

{% set maxarity=16 %}

{%- macro typeParamsDeclList(narg, rest) -%}
<{% for i in range(narg) -%}
in P{{i + 1}}, {{""}}
{%- endfor -%}
{%- if rest %}in PR, {% endif %}{{rvar}}out R>
{%- endmacro %}

{%- macro typeParamsList(narg, rest) -%}
<{% for i in range(narg) -%}
P{{i + 1}}, {{""}}
{%- endfor -%}
{%- if rest %}{{rest}}, {% endif %}R>
{%- endmacro %}

{% macro erasedTypeArgsList(narg) -%}
<{% for i in range(narg) %}Any, {% endfor %}Any>
{%- endmacro %}

{%- macro signature(narg, rest) -%}
({% for i in range(narg) -%}
p{{i + 1}}: P{{i + 1}}{% if not loop.last or rest %}, {% endif %}
{%- endfor -%}
{%- if rest %}...r: FixedArray<PR>{% endif %}): R
{%- endmacro %}

{%- macro erasedSignature(narg, rest) -%}
({% for i in range(narg) -%}
p{{i + 1}}: Any{% if not loop.last or rest %}, {% endif %}
{%- endfor -%}
{%- if rest %}...r: FixedArray<Any>{% endif %}): Any
{%- endmacro %}

{%- macro listArgs(from, to) -%}
{% for i in range(from, to) -%}
p{{i + 1}}{% if not loop.last %}, {% endif %}
{%- endfor %}
{%- endmacro %}

{%- macro listArgArrayLoads(to) -%}
{% for i in range(to) -%}
r[{{i}}]{% if not loop.last %}, {% endif %}
{%- endfor %}
{%- endmacro %}

{%- macro invokeName(narg, suffix) %}invoke{{suffix}}{{narg}}{% endmacro %}

native function getFunctionObjectNameFromAnnotation(func: Object): string;

export @interface NamedFunctionObject {
    name: string;
}

export interface Function {
    unsafeCall(...r: FixedArray<Any>): Any
    get name(): string;
}

export interface FunctionN<R> extends Function {
}

export abstract class LambdaN implements FunctionN<Any> {
    get name(): string {
        return getFunctionObjectNameFromAnnotation(this as Object);
    }
}

{%- macro defineChainingHelper(name, narg, erasedArgs) -%}
export interface __{{name}}{{narg}} extends {{name}}{{narg}}{{erasedTypeArgsList(erasedArgs)}}
{%- endmacro %}

{%- macro defineLambdaHelper(lambda, name, narg) -%}
export abstract class {{lambda}}{{narg}} implements __{{name}}{{narg}}
{%- endmacro %}

{% for narg in range(maxarity + 1) %}
export interface FunctionR{{ narg }}{{ typeParamsDeclList(narg, True) }}
    extends Function{% if not loop.last %}, __FunctionR{{narg + 1}}{% endif %}{% if loop.last %}, FunctionN<Any>{% endif %}
{
    {{invokeName(narg, "R")}}{{ signature(narg, True) }};
}
export interface Function{{ narg }}{{ typeParamsDeclList(narg) }}
    extends FunctionR{{narg}}{{ typeParamsList(narg, "Any") }}{% if not loop.last %}, __Function{{narg + 1}}{% endif %}
{
    {{invokeName(narg)}}{{ signature(narg) }};
}
{{ defineChainingHelper("FunctionR", narg, narg + 1) }} {}
{{ defineChainingHelper("Function", narg, narg) }} {}
{{ defineLambdaHelper("LambdaR", "FunctionR", narg) }} {

    get name(): string {
        return getFunctionObjectNameFromAnnotation(this as Object)
    }

    abstract {{invokeName(narg, "R")}}{{erasedSignature(narg, True)}};
{%- if narg == 0 %}
    final unsafeCall(...r: FixedArray<Any>): Any {
        return this.{{invokeName(narg, "R")}}(...r)
    }
{%- else %}
    final unsafeCall(...r: FixedArray<Any>): Any {
        if (r.length < {{narg}}) { throw new ArgumentsUnderapplicationError() }
        return this.{{invokeName(narg, "R")}}({{listArgArrayLoads(narg)}}{{", " if narg != 0 }}
            ...Runtime.removeFrontElementsStub(r, {{narg}}))
    }
{%- endif %}
{%- for extNarg in range(narg + 1, maxarity + 1) %}
    final {{invokeName(extNarg, "R")}}{{erasedSignature(extNarg, True) }} {
        return this.{{invokeName(narg, "R")}}({{listArgs(0, narg)}}{{", " if narg != 0 }}
            ...Runtime.addFrontElementsStub(r, [{{listArgs(narg, extNarg)}}]))
    }
{%- endfor %}
}
{{ defineLambdaHelper("Lambda", "Function", narg) }} {
    abstract {{invokeName(narg)}}{{erasedSignature(narg)}};
    final unsafeCall(...r: FixedArray<Any>): Any {
        if (r.length < {{narg}}) { throw new ArgumentsUnderapplicationError() }
        return this.{{invokeName(narg)}}({{listArgArrayLoads(narg)}})
    }

    get name(): string {
        return getFunctionObjectNameFromAnnotation(this as Object)
    }

{%- for extNarg in range(narg + 1, maxarity + 1) %}
    final {{invokeName(extNarg)}} {{erasedSignature(extNarg, False)}} {
        return this.{{invokeName(narg)}}({{listArgs(0, narg)}})
    }
{%- endfor %}
{%- for extNarg in range(narg, maxarity + 1) %}
    final {{invokeName(extNarg, "R")}}{{erasedSignature(extNarg, True) }} {
        return this.{{invokeName(narg)}}({{listArgs(0, narg)}})
    }
{%- endfor %}
}
{% endfor %}
